<!-- 手写响应式 -->
<template>
    <button>click</button>
    <span>span</span>

    <!-- 双向绑定 -->
    <input type="text">

    <el-button @click="handleCount">handleCount+</el-button>

    <el-button @click="stop">stop</el-button>

    {{ doubled }}

    <h3>--------------代理函数,缓存执行结果---------------</h3>

    <button @click="clickProxyFn">click</button>
    <button @click="clickProxyFn5">click5</button>

</template>

<script setup>
import { onMounted, effectScope, ref, computed, watch, watchEffect } from "vue"

const scope = effectScope()

const counter = ref(1)

const handleCount = () => {
    counter.value += 1
}
const stop = () => {
    scope.stop()
}
let doubled
const res = scope.run(() => {
    doubled = computed(() => counter.value * 2)

    watch(doubled, () => console.log(doubled.value))

    watchEffect(() => console.log('Count: ', doubled.value))
    return 1
})

console.log(res);

onMounted(() => {
    const inputEl = document.querySelector('input')
    const btnEl = document.querySelector('button')
    const spanEl = document.querySelector('span')


    // 原始对象
    const data = {
        value: 0
    }

    // 副作用函数的桶
    const bucket = new Set()

    // 副作用函数
    let activeEffect = {}

    // 收集副作用函数的函数
    const effect = (effectName, fn) => {
        activeEffect[effectName] = fn
        fn()
    }

    // 代理对象
    const obj = new Proxy(data, {
        get(target, key) {
            if (activeEffect) bucket.add(activeEffect)
            console.log('get');
            return Reflect.get(target, key)
        },
        set(target, key, newValue) {
            Reflect.set(target, key, newValue)
            bucket.forEach(e => {
                if (e[key]) {
                    e[key]()
                }
            })
            return true
        }
    })

    // 收集副作用函数
    effect('value', () => {
        inputEl.value = obj.value
        spanEl.innerText = obj.value
    })

    // 点击事件
    btnEl.onclick = function () {
        obj.value += 1
    }

    // 监听输入
    inputEl.addEventListener('input', (e) => {
        obj.value = Number(e.target.value)
    })
})

// proxy代理函数
const fn = (a) => {
    console.log(a);
    return a * 2
}
const getProxyFn = (fn, cache = new Map()) => {
    return new Proxy(fn, {
        apply: (target, context, args) => {
            const arg = args[0]
            if (cache.has(arg)) {
                return cache.get(arg)
            } else {
                const res = target(arg)
                cache.set(arg, res)
                return res
            }
        }
    })
}
const proxyFn = getProxyFn(fn)

const count = ref(0)
const clickProxyFn = () => {
    proxyFn(count.value++)
}
const clickProxyFn5 = () => {
    proxyFn(5)
}
</script>

<style scoped>
</style>